/******************************************************************************
 *      Mestrado em Ciencia da Computacao - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinicius Bueno
 *****************************************************************************/
/* tcptimer.c - tcptimer */

#include "tcptimer.h"
#include "tcb.h"
#include "port.h"
#include "thread.h"

sem_t	tqmutex;
struct	tqent	*tqhead;


/*------------------------------------------------------------------------
 *  tcptimer -  TCP timer process
 *------------------------------------------------------------------------
 */
void tcptimer()
{
    
    long now, lastrun;		// times from system clock
    int	delta;			// time since last iteration
    struct tqent *tq;		// temporary delta list ptr
    long ctr100 = CLOCKS_PER_SEC/100;

    lastrun = ctr100;		// initialize to "now"
    sem_init(&tqmutex, 0, 1);	// mutual exclusion semaphore

    //signal(Net.sema);		// start other network processes

    while(1)
    {
        thread_wait(timer_thread);
        wait_(10*TIMERGRAN);	// real-time delay

        if (tqhead == 0) {	// block timer process if delta
            thread_suspend(timer_thread);	//   list is empty
            continue ;
        }

        sem_wait(&tqmutex);
        now = ctr100;
        delta = now - lastrun;	// compute elapsed time

        // Note: check for possible clock reset (time moved
        // backward or delay was over an order of magnitude too
        // long)

        if (delta < 0 || delta > TIMERGRAN*100)
            delta = TIMERGRAN*10;	// estimate the delay
        lastrun = now;
        while (tqhead != 0  &&  tqhead->tq_timeleft <= delta) {
            delta -= tqhead->tq_timeleft;
            
            if(port_countmsg(tqhead->tq_port) <= tqhead->tq_portlen)
                port_sendmsg(tqhead->tq_port, (int)tqhead->tq_msg);

            tq = tqhead;
            tqhead = tqhead->tq_next;
            //freemem(tq, sizeof(struct tqent));
            free(tq);
        }
        if(tqhead)
            tqhead->tq_timeleft -=delta;

        sem_post(&tqmutex);
    }
    
}
